package com.iflytek.autoCompareTool.service;


import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.iflytek.autoCompareTool.common.Config;
import com.iflytek.autoCompareTool.common.Constants;
import com.iflytek.autoCompareTool.common.DBManager;
import com.iflytek.autoCompareTool.common.TaskManager;
import com.iflytek.autoCompareTool.model.InputInfo;
import com.iflytek.autoCompareTool.model.OutputData;
import com.iflytek.autoCompareTool.model.OutputInfo;
import com.iflytek.autoCompareTool.model.TestSet;
import com.iflytek.autoCompareTool.utils.HttpUtil;
import org.apache.commons.dbutils.QueryRunner;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.sql.SQLException;
import java.text.DecimalFormat;
import java.util.List;
import java.util.concurrent.CountDownLatch;

/**
 * @author llchen12
 * @date 2018/6/5
 */
public class Worker implements Runnable {


    private static Logger logger = LoggerFactory.getLogger(Worker.class);

    private CountDownLatch countDownLatch;

    /**
     * 不一致部分
     */
    private OutputData diffPart;

    /**
     * 总结果
     */
    private OutputData result;

    /**
     * 测试集
     */
    private List<TestSet> testSetList;

    private InputInfo inputInfo;

    /**
     * 当前任务的id
     */
    private Integer id;

    /**
     * 同一批测试任务中，该FileName分类测试集，之前的测试集内的数量
     */
    private int preNum;


    public Worker(Integer id, InputInfo inputInfo, CountDownLatch countDownLatch, OutputData diffPart, OutputData result, List<TestSet> testSetList, int preNum) {
        this.id = id;
        this.inputInfo = inputInfo;
        this.countDownLatch = countDownLatch;
        this.diffPart = diffPart;
        this.result = result;
        this.testSetList = testSetList;
        this.preNum = preNum;
    }


    @Override
    public void run() {

        for (TestSet testSet : testSetList) {
            //**判断任务是否被手动停止**
            if (TaskManager.isCancel(id)) {
                break;
            }

            if (inputInfo.getSingleEnv() == 1) {
                //****不对比，获取线上结果*****/
                String url = getUrl(testSet, inputInfo.getCmpEnv(), inputInfo.getCmpOther());

                OutputInfo out;
                try {
                    JSONObject json = JSONObject.parseObject(HttpUtil.doGet(url, 3));
                    out = getNoComResult(json);
                } catch (Exception e) {
                    logger.error("测试任务:uid:{} 网页访问超时或者内容为空", testSet.getUid(), e);
                    out = new OutputInfo();
                    out.setCmpSemantic("网页请求超时或者JSON解析失败，请手动处理");
                }

                out.setNum(testSet.getNum());
                out.setAppid(testSet.getAppid());
                out.setUsrid(testSet.getUsrid());
                out.setParameter(testSet.getParameter());
                out.setUid(testSet.getUid());
                out.setUserData(testSet.getUserData());
                out.setText(testSet.getText());
                out.setC1Url(url);

                try {
                    result.add(out);
                } catch (Exception e) {
                    logger.error("添加结果集失败", e);
                }

            } else {
                //****获取两个环境对比结果*****/
                String base = getUrl(testSet, inputInfo.getBaseEnv(), inputInfo.getBaseOther());
                String cmp = getUrl(testSet, inputInfo.getCmpEnv(), inputInfo.getCmpOther());

                Comparator compare = new Comparator(testSet.getUid(), testSet.getUsrid(), testSet.getAppid(), testSet.getParameter(),
                        testSet.getUserData(), testSet.getText(), base, cmp, testSet.getFileName(), inputInfo.getAnswer());

                JSONObject baseJo, cmpJo;
                OutputInfo out;
                try {
                    cmpJo = JSON.parseObject(HttpUtil.doGet(cmp, 3));
                    if ("expect".equals(inputInfo.getBaseEnv())) {
                        compare.eptCmpEnv(cmpJo, testSet.getService(), testSet.getSemantic(), testSet.getOperation(), testSet.getAnswer());
                    } else {
                        baseJo = JSON.parseObject(HttpUtil.doGet(base,3));
                        compare.envCmpEnv(baseJo, cmpJo);
                    }
                    out = compare.getOutputInfo();
                } catch (Exception e) {
                    out = compare.getOutputInfo();
                    logger.error("测试任务:uid:{} 网页访问超时或者内容为空", testSet.getUid(), e);
                    out.setFinalResult(Constants.DIFFER);
                    out.setCmpSemantic("网页请求超时或者JSON解析失败，请手动处理");
                }
                try {
                    out.setNum(testSet.getNum());
                    result.add(out);
                    out.setNum(testSet.getNum() + preNum);
                    diffPart.addDiff(out);
                } catch (Exception e) {
                    logger.error("添加结果集失败", e);
                }

            }

            //**每执行accuracy条更新百分比**/
            Integer time = TaskManager.increaseAndGetTaskFinishCount(id);
            if (time != null && time % 50 == 0) {

                Double progress = TaskManager.getTaskProgress(id);
                DecimalFormat progressformat = new DecimalFormat("#0.00");
                //** 首先查看任务有没有被手动停止 **/

                if (TaskManager.isCancel(id)) {
                    logger.debug(id + "号任务被手动终止，取消执行剩余任务");
                    break;
                } else {
                    //防止执行进度>=99.5时被五入为100，导致自动终止
                    if (progress >= 99.0 && progress < 100.0) {
                        progress = 99.0;
                    }
                    updateProgress(progressformat.format(progress), id);
                    logger.debug(id + "号任务已执行进度：" + progressformat.format(progress));
                }
            }
        }
        countDownLatch.countDown();
    }


    private void updateProgress(Object progress, Integer id) {
        String sql = "update tool_testupload set progress=? " +
                "where id=?";
        QueryRunner qr = DBManager.getInstance().getAiuiManagerQr();
        try {
            qr.update(sql, progress, Math.abs(id));
        } catch (SQLException e) {
            logger.error("更新进度异常：", e);
        }
    }


    /**
     * 获取为对比的原始数据
     */
    private OutputInfo getNoComResult(JSONObject json) {
        OutputInfo out = new OutputInfo();
        if (json.containsKey("service")) {
            //**获取业务**/
            if (json.containsKey("service")) {
                out.setClService(json.getString("service"));
            }

            //**获取结果**/
            //*** add  支持4.0协议修改*/
            Object semantic = json.get("semantic");
            if (semantic != null) {
                if (semantic instanceof JSONObject) {
                    out.setClSemantic((JSONObject) semantic);
                } else if (semantic instanceof JSONArray) {
                    JSONObject jsonObject = ((JSONArray) semantic).getJSONObject(0);
                    out.setClSemantic(jsonObject);
                    out.setClOperation(jsonObject.get("intent").toString());
                }
            }

            //**获取操作**/
            //*** add  支持4.0协议修改*/
            if (json.containsKey("operation")) {
                out.setClOperation(json.getString("operation"));
            }
            //**获取Answer**/
            Object answer = json.get("answer");
            if (answer != null) {
                if (answer instanceof JSONObject) {
                    out.setClAnswer(((JSONObject) answer).getString("text"));
                } else {
                    out.setClAnswer(answer.toString());
                }
            }
            //**获取UUID**/
            if (json.containsKey("uuid")) {
                out.setC1Uuid(json.getString("uuid"));
            }
            //**获取SID**/
            if (json.containsKey("sid")) {
                out.setC1Sid(json.getString("sid"));
            }
        } else {
            if (json.containsKey("rc")) {
                out.setClService("rc=" + json.getString("rc"));
            }
        }
        return out;
    }


    /**
     * 获取环境相对应的url
     */
    private String getUrl(TestSet td, String conf, String other) {
        String url = "";
        if ("expect".equals(conf)) {
            return url;
        } else if ("online".equals(conf)) {
            url = Config.URL_ENV_ONLINE;
        } else if ("onlinepre".equals(conf)) {
            url = Config.URL_ENV_PRE;
        } else if ("nlu_test".equals(conf)) {
            url = Config.URL_ENV_NLU_TEST;
        } else if ("athena_move".equals(conf)) {
            url = Config.URL_ENV_ATHENA_MOVE;
        } else if ("kcloud_current".equals(conf)) {
            url = Config.URL_ENV_KCLOUD_CURRENT;
        } else if ("kcloud_move_pk".equals(conf)) {
            url = Config.URL_ENV_KCLOUD_MOVE_PK;
        } else if ("kcloud_move_nlu".equals(conf)) {
            url = Config.URL_ENV_KCLOUD_MOVE_NLU;
        } else if ("other_url".equals(conf)) {
            url = other;
        }
        StringBuilder ret = new StringBuilder(url);
        String parameter = td.getParameter();
        if (StringUtils.isNotBlank(parameter)){
            if (!parameter.startsWith("&")) {
                parameter = "&" + parameter;
            }
            //支持4.0协议    做以下修改
            if (parameter.contains("ver=4.0")) {
                url = url.replace("ver=3.1&", "");
                url = url.replace("ver=2.0&", "");
            }
            ret.append(parameter);
        }


        if (StringUtils.isNotBlank(td.getAppid())) {
            ret.append("&appid=").append(td.getAppid());
        }
        if (StringUtils.isNotBlank(td.getUsrid())) {
            ret.append("&usrid=").append(td.getUsrid());
        }
        if (StringUtils.isNotBlank(td.getText())) {
            ret.append("&text=").append(HttpUtil.encodeURLStr(td.getText()));
        }
        if (StringUtils.isNotBlank(td.getUserData())) {
            ret.append("&user_data=").append(HttpUtil.encodeURLStr(td.getUserData()));
        }
        if (StringUtils.isNotBlank(td.getUid())) {
            ret.append("&uid=").append(td.getUid());
        }
        if (other != null && !"".equals(other) && !"other_url".equals(conf)) {
            ret.append("&").append(other);
        }
        return ret.toString();
    }
}
